package znet

import (
	"log"
	"strconv"
	"zinxp/utils"
	"zinxp/ziface"
)

type MsgHandle struct {
	//存放每个MsgId 所对应的处理方法的map属性
	Apis map[uint32]ziface.IRouter
	//业务工作worker池的数量
	/*
	工作池的数量，因为TaskQueue中的每个队列应该是和一个Worker对应的，所以我们在创建TaskQueue中队列数量要和Worker的数量一致
	 */
	WorkerPoolSize uint32
	//worker的消息队列
	/*
	Request请求信息的channel集合。用来缓冲提供worker调用的Request请求信息，worker会从对应的队列中获取客户端的请求数据并且处理掉。
	 */
	TaskQueue []chan ziface.IRequest
}

func NewMsgHandle() *MsgHandle {
	return &MsgHandle{
		Apis: make(map[uint32]ziface.IRouter),
		WorkerPoolSize: utils.GlobalObject.WorkerPoolSize,
		TaskQueue: make([]chan ziface.IRequest,utils.GlobalObject.WorkerPoolSize),
	}
}

func (mh *MsgHandle) DoMsgHandler(request ziface.IRequest) {
	handler, ok := mh.Apis[request.GetMsgID()]
	if !ok {
		log.Println("api msgID= ", request.GetMsgID(), " is not found!")
		return
	}

	handler.PreHandle(request)
	handler.Handle(request)
	handler.PostHandle(request)
}

func (mh *MsgHandle) AddRouter(msgId uint32, router ziface.IRouter) {
	if _, ok := mh.Apis[msgId]; ok {
		panic("repeated api,msgid = " + strconv.Itoa(int(msgId)))
	}
	mh.Apis[msgId] = router
	log.Println("Add api msgId = ", msgId)
}

func (mh *MsgHandle)StartOneWorker(workerID int,taskQueue chan ziface.IRequest)  {
	log.Println("Worker ID = ",workerID, " Is Started")
	//不断等待消息队列的消息
	for  {
		select{
		case request := <- taskQueue:
			mh.DoMsgHandler(request)
		}
	}
}

func (mh *MsgHandle) StartWorkerPool()  {
	//遍历需要启动的worker的数量，依次启动
	for i:= 0;i < int(mh.WorkerPoolSize);i++{
		mh.TaskQueue[i] = make(chan ziface.IRequest,utils.GlobalObject.MaxWorkerTaskLen)
		//启动当前worker，阻塞等待对应的任务队列是否有任务传入
		go mh.StartOneWorker(i,mh.TaskQueue[i])
	}
}

func (mh *MsgHandle) SendMsgToTaskQueue(request ziface.IRequest)  {
	//根据connID来分配当前的连接由哪个worker负责处理
	//轮询
	workerID := request.GetConnection().GetConnID() % mh.WorkerPoolSize
	log.Println("Add ConnID= ",request.GetConnection().GetConnID()," request msgID = ",request.GetMsgID(),"to workerID=",workerID )
	//将请求发送给任务队列
	mh.TaskQueue[workerID] <- request
}